#ifndef GY_POINTUSERDATA_H
#define GY_POINTUSERDATA_H

#endif // GY_POINTUSERDATA_H

#include <QObject>
#include "../../LuaInterpreter/lua.hpp"

struct Point {
    double X;
    double Y;
    Point operator+(const Point& other) const {
        return Point{X+other.X,Y+other.Y};
    };
    Point operator-(const Point& other) const {
        return Point{X-other.X,Y-other.Y};
    };
    Point operator*(const Point& other) const {
        return Point{X*other.X,Y*other.Y};
    };
    Point operator/(const Point& other) const {
        return Point{X/other.X,Y/other.Y};
    };
};

//  自定义函数,数据类型
const char* luaL_getUdataName(lua_State* L, int idx,void* & pdata)
{
    pdata = lua_touserdata(L, idx);
    if (pdata != NULL)
    {
        if (lua_getmetatable(L, idx))
        {
            // 获取元表中的__name字段
            lua_getfield(L, -1, "__name");
            // 将__name字段转换为字符串
            const char* name = lua_tostring(L, -1);
            return name;
        }
    }
    return "";
}

//  加法函数
int add_point(lua_State* L) {
    Point* p1 = static_cast<Point*>(lua_touserdata(L, 1));
    if(!lua_isuserdata(L ,2))
    {
        double result = lua_tonumber(L, 2);
        Point* p3 = static_cast<Point*>(lua_newuserdata(L, sizeof(Point)));
        p3->X = p1->X+result;
        p3->Y = p1->Y+result;
        luaL_getmetatable(L, "Point");
        lua_setmetatable(L, -2);
    }
    else
    {
        void* pData=nullptr;
        const char* typeName=luaL_getUdataName(L,2,pData);
        //strcmp两字符串相等返回0
        if(!strcmp(typeName,"point"))
        {
            Point* p2 = static_cast<Point*>(pData);
            Point* p3 = static_cast<Point*>(lua_newuserdata(L, sizeof(Point)));
            *p3 = *p1 + *p2;
            luaL_getmetatable(L, "Point");
            lua_setmetatable(L, -2);
        }
    }
    return 1;
}

int sub_point(lua_State* L) {
    Point* p1 = static_cast<Point*>(lua_touserdata(L, 1));
    if(!lua_isuserdata(L ,2))
    {
        double result = lua_tonumber(L, 2);
        Point* p3 = static_cast<Point*>(lua_newuserdata(L, sizeof(Point)));
        p3->X = p1->X-result;
        p3->Y = p1->Y-result;
        luaL_getmetatable(L, "Point");
        lua_setmetatable(L, -2);
    }
    else
    {
        void* pData=nullptr;
        const char* typeName=luaL_getUdataName(L,2,pData);
        //strcmp两字符串相等返回0
        if(!strcmp(typeName,"point"))
        {
            Point* p2 = static_cast<Point*>(pData);
            Point* p3 = static_cast<Point*>(lua_newuserdata(L, sizeof(Point)));
            *p3 = *p1 - *p2;
            luaL_getmetatable(L, "Point");
            lua_setmetatable(L, -2);
        }
    }
    return 1;
}

int mul_point(lua_State* L) {
    Point* p1 = static_cast<Point*>(lua_touserdata(L, 1));
    if(!lua_isuserdata(L ,2))
    {
        double result = lua_tonumber(L, 2);
        Point* p3 = static_cast<Point*>(lua_newuserdata(L, sizeof(Point)));
        p3->X = p1->X*result;
        p3->Y = p1->Y*result;
        luaL_getmetatable(L, "Point");
        lua_setmetatable(L, -2);
    }
    else
    {
        void* pData=nullptr;
        const char* typeName=luaL_getUdataName(L,2,pData);
        //strcmp两字符串相等返回0
        if(!strcmp(typeName,"point"))
        {
            Point* p2 = static_cast<Point*>(pData);
            Point* p3 = static_cast<Point*>(lua_newuserdata(L, sizeof(Point)));
            *p3 = (*p1) * (*p2);
            luaL_getmetatable(L, "Point");
            lua_setmetatable(L, -2);
        }
    }
    return 1;
}

int div_point(lua_State* L) {
    Point* p1 = static_cast<Point*>(lua_touserdata(L, 1));
    if(!lua_isuserdata(L ,2))
    {
        double result = lua_tonumber(L, 2);
        Point* p3 = static_cast<Point*>(lua_newuserdata(L, sizeof(Point)));
        p3->X = p1->X/result;
        p3->Y = p1->Y/result;
        luaL_getmetatable(L, "Point");
        lua_setmetatable(L, -2);
    }
    else
    {
        void* pData=nullptr;
        const char* typeName=luaL_getUdataName(L,2,pData);
        //strcmp两字符串相等返回0
        if(!strcmp(typeName,"point"))
        {
            Point* p2 = static_cast<Point*>(pData);
            Point* p3 = static_cast<Point*>(lua_newuserdata(L, sizeof(Point)));
            *p3 = (*p1) / (*p2);
            luaL_getmetatable(L, "Point");
            lua_setmetatable(L, -2);
        }
    }
    return 1;
}

// 定义Point元表的__index元方法
int point_index(lua_State* L) {
    Point* p = static_cast<Point*>(lua_touserdata(L, 1));
    const char* key = lua_tostring(L, 2);
    if (strcmp(key, "X") == 0) {
        lua_pushnumber(L, p->X);
    } else if (strcmp(key, "Y") == 0) {
        lua_pushnumber(L, p->Y);
    } else {
        lua_pushnil(L);
    }
    return 1;
}

// 定义Point元表的__newindex元方法
int point_newindex(lua_State* L) {
    Point* p = static_cast<Point*>(lua_touserdata(L, 1));
    const char* key = lua_tostring(L, 2);
    if (strcmp(key, "X") == 0) {
        p->X = lua_tointeger(L, 3);
    } else if (strcmp(key, "Y") == 0) {
        p->Y = lua_tointeger(L, 3);
    }
    return 0;
}

